import { $set } from '@feng3d/serialization';
import { CubeTextureLoader3D, Mesh3D, MeshBasicMaterial3D, Node3D, PerspectiveCamera3D, Scene3D, SphereGeometry3D, WebGLRenderer3D } from 'feng3d-three';
import { ParallaxBarrierEffect3D } from '../../extension/effects/ParallaxBarrierEffect3D';

const rootPath = '../../';

let container: HTMLDivElement;
let camera: PerspectiveCamera3D;
let scene: Scene3D;
let renderer: WebGLRenderer3D;
let effect: ParallaxBarrierEffect3D;

const spheres: Mesh3D[] = [];

let mouseX = 0;
let mouseY = 0;

let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;

document.addEventListener('mousemove', onDocumentMouseMove);

init();
animate();

function init()
{
    container = document.createElement('div');
    document.body.appendChild(container);

    camera = new Node3D().addComponent('PerspectiveCamera3D', { fov: 60, aspect: window.innerWidth / window.innerHeight, near: 0.01, far: 100 });
    camera.entity.position.z = 3;
    camera.focalLength = 3;

    const path = `${rootPath}textures/cube/pisa/`;
    const format = '.png';
    const urls = [
        `${path}px${format}`, `${path}nx${format}`,
        `${path}py${format}`, `${path}ny${format}`,
        `${path}pz${format}`, `${path}nz${format}`
    ];

    const textureCube = new CubeTextureLoader3D().load(urls);

    scene = new Node3D().addComponent('Scene3D');
    scene.background = textureCube;

    const geometry = $set(new SphereGeometry3D(), { radius: 0.1, widthSegments: 32, heightSegments: 16 });
    const material = $set(new MeshBasicMaterial3D(), { color: { value: 0xffffff }, envMap: textureCube });

    for (let i = 0; i < 500; i++)
    {
        const mesh = new Node3D().addComponent('Mesh3D', { geometry, material });

        mesh.entity.position.x = Math.random() * 10 - 5;
        mesh.entity.position.y = Math.random() * 10 - 5;
        mesh.entity.position.z = Math.random() * 10 - 5;

        mesh.entity.scale.x = mesh.entity.scale.y = mesh.entity.scale.z = Math.random() * 3 + 1;

        scene.entity.addChild(mesh.entity);

        spheres.push(mesh);
    }

    //

    renderer = scene.addComponent('WebGLRenderer3D');
    renderer.setPixelRatio(window.devicePixelRatio);
    container.appendChild(renderer.domElement);

    const width = window.innerWidth || 2;
    const height = window.innerHeight || 2;

    effect = new ParallaxBarrierEffect3D(renderer);
    effect.setSize(width, height);

    //     //

    window.addEventListener('resize', onWindowResize);
}

function onWindowResize()
{
    windowHalfX = window.innerWidth / 2;
    windowHalfY = window.innerHeight / 2;

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    effect.setSize(window.innerWidth, window.innerHeight);
}

function onDocumentMouseMove(event)
{
    mouseX = (event.clientX - windowHalfX) / 100;
    mouseY = (event.clientY - windowHalfY) / 100;
}

//

function animate()
{
    requestAnimationFrame(animate);

    render();
}

function render()
{
    const timer = 0.0001 * Date.now();

    camera.entity.position.x += (mouseX - camera.entity.position.x) * 0.05;
    camera.entity.position.y += (-mouseY - camera.entity.position.y) * 0.05;

    camera.entity.lookAt(scene.entity.position);

    for (let i = 0, il = spheres.length; i < il; i++)
    {
        const sphere = spheres[i];

        sphere.entity.position.x = 5 * Math.cos(timer + i);
        sphere.entity.position.y = 5 * Math.sin(timer + i * 1.1);
    }

    effect.render(scene, camera);
}
